using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Windows.Media;
using Styx;
using Styx.Common;
using Styx.CommonBot;
using Styx.Helpers;
using Styx.Localization;
using GreyMagic;
using Styx.Plugins;
using Talented.Forms;
using Styx.WoWInternals;

namespace Talented
{
    public class Talented : HBPlugin
    {
        #region Non-HB Specific

        private static bool HasLearnedMajorTree { get { return StyxWoW.Me.Specialization != WoWSpec.None; } }

        private static int CurrentSpecialization { get { return Lua.GetReturnVal<int>("return GetSpecialization()", 0); } }

        public void SetSpecialization(string name, int index)
        {
            Logging.Write(Colors.LawnGreen, "[Talented2] Setting class specialization to {0} [Index: {1}]", name, index);
            Lua.DoString("SetSpecialization({0})", index);
        }

        private static void LearnTalent(int tier, int index)
        {
            Lua.DoString(string.Format("LearnTalent({0})", (tier - 1) * 3 + index));
        }

        private static IEnumerable<TalentPlacement> BuildLearnedTalents()
        {
            var ret = new List<TalentPlacement>();

            using (StyxWoW.Memory.AcquireFrame())
            {
                for (int tierIndex = 0; tierIndex < 6; tierIndex++)
                {
                    for (int talentIndex = 1; talentIndex <= 3; talentIndex++)
                    {
                        var index = tierIndex * 3 + talentIndex;
                        var vals = Lua.GetReturnValues("return GetTalentInfo(" + index + ")");
                        var name = vals[0];
                        var learned = int.Parse(vals[4]) != 0;

                        if (learned)
                        {
                            ret.Add(new TalentPlacement(tierIndex + 1, talentIndex, name));
                        }
                    }
                }
            }

            return ret;
        }

        private void DoCheck()
        {
            try
            {
                using (StyxWoW.Memory.AcquireFrame())
                {
                    if (!HasLearnedMajorTree)
                    {
                        SetSpecialization(_talentBuild.BuildName, _talentBuild.Specialization);
                    }
                    else if (CurrentSpecialization != _talentBuild.Specialization)
                    {
                        Logging.Write(Colors.Red,
                                      "[Talented2] Your current talent specialization doesn't fit to the selected talent build. Please change it from Plugin settings.");
                        return;
                    }

                    var learned = BuildLearnedTalents().ToList();
                    var wanted = _talentBuild.TalentPlacements;

                    foreach (var tp in wanted)
                    {
                        // If our level is lower then needed level for this tier skip it.
                        if (StyxWoW.Me.Level < tp.Tier*15)
                            continue;

                        // If there is any talents learned in this tier skip it
                        var isLearned = learned.Any(lt => lt.Tier == tp.Tier);

                        if (!isLearned)
                        {
                            Logging.Write(Colors.LawnGreen, "[Talented2] Learning talent {0} [Tier: {1} Index: {2}]",
                                          tp.Name, tp.Tier, tp.Index);
                            LearnTalent(tp.Tier, tp.Index);
                        }
                    }
                }
            }
            catch (Exception)
            {
                DoCheck();
            }
        }

        #endregion

        private TalentTree _talentBuild;
        private bool _buildFailed;
        private int _lastLevel;
        private ulong _lastGuid;
        public override void Pulse()
        {
            if (_talentBuild == null || _talentBuild.BuildName != TalentedSettings.Instance.ChoosenTalentBuildName || _talentBuild.Class != TalentedSettings.Instance.ChoosenTalentClass)
            {
                try
                {
                    _talentBuild = TalentedSettings.Instance.ChoosenTalentBuild;
                    _buildFailed = false;

                    if (_talentBuild != null)
                        Logging.Write(Colors.LawnGreen, "[Talented2] Using talent build: {0}-{1}", _talentBuild.Class, _talentBuild.BuildName);
                }
                catch (Exception ex)
                {
                    if (_buildFailed)
                        return;

                    _buildFailed = true;
                    Logging.Write(Colors.Red, "[Talented2] One or more talent builds couldn't be parsed successfully. Please repair the talent build files in Data/Talent Builds folder. Exception:", ex.Message);
                    return;
                }
            }

            if (_talentBuild == null)
            {
                Logging.Write(Colors.Red, "[Talented2] You have not yet selected a talent build! Please open the form and select one");
                return;
            }

            if (_talentBuild != null && _talentBuild.Class != StyxWoW.Me.Class && StyxWoW.Me.Level > 0)
            {
                Logging.Write(Colors.Red, "[Talented2] This build is not meant for you class! Please select another talent build");
                return;
            }

            var myGuid = StyxWoW.Me.Guid;

            if (myGuid != _lastGuid)
            {
                _lastLevel = 0;
                _lastGuid = myGuid;
            }

            var myLevel = StyxWoW.Me.Level;
            // No talents below level 10
            if (myLevel < 10)
                return;

            if (myLevel > _lastLevel)
            {
                DoCheck();
                _lastLevel = myLevel;
            }
        }

        public override string Name { get { return Globalization.Talented_Name; } }

        public override string Author { get { return "The Buddy Team"; } }

        public override Version Version { get { return new Version(2, 0, 0); } }

        public override bool WantButton { get { return true; } }

        public override string ButtonText { get { return "Select Talent Build"; } }

        public override void OnButtonPress()
        {
            var config = new FormConfig();
            config.ShowDialog();
        }
    }
}
